/**
 * @author Simon Richardson - simon@ustwo.co.uk
 */
package org.osflash.signals.natives.sets;

import asunit.asserts.AssertNotNull;
import asunit.asserts.AssertSame;
import asunit.asserts.AssertTrue;
import asunit.asserts.Fail;
import asunit.framework.IAsync;
import org.osflash.signals.ISlot;
import flash.display.Sprite;
import flash.events.Event;

class DisplayObjectSignalSetTest {

	@:meta(Inject())
	public var async : IAsync;
	var sprite : Sprite;
	var signalSet : DisplayObjectSignalSet;
	@:meta(Before())
	public function setUp() : Void {
		sprite = new Sprite();
		signalSet = new DisplayObjectSignalSet(sprite);
	}

	@:meta(After())
	public function tearDown() : Void {
		signalSet.removeAll();
		signalSet = null;
		sprite = null;
	}

	function newEmptyHandler() : Dynamic {
		return function(e : Dynamic) : Void {
		}
;
	}

	function handleEvent(event : Event) : Void {
		assertSame(sprite, event.target);
	}

	function failIfCalled(e : Event) : Void {
		fail("This event handler should not have been called.");
	}

	//////
	@:meta(Test())
	public function numListeners_should_be_zero() : Void {
		assertTrue("Number of listeners should be 0.", signalSet.numListeners == 0);
	}

	//////
	@:meta(Test())
	public function signals_should_be_not_null() : Void {
		assertNotNull("Signals should not be null.", signalSet.signals);
	}

	//////
	@:meta(Test())
	public function signals_length_should_be_empty() : Void {
		assertTrue("Signals length should be 0.", signalSet.signals.length == 0);
	}

	//////
	@:meta(Test())
	public function signals_length_should_be_zero_after_removeAll() : Void {
		signalSet.removeAll();
		assertTrue("Signals length should be 0.", signalSet.signals.length == 0);
	}

	//////
	@:meta(Test())
	public function numListeners_should_be_zero_after_removeAll() : Void {
		signalSet.removeAll();
		assertTrue("Number of listeners should be 0.", signalSet.numListeners == 0);
	}

	//////
	@:meta(Test())
	public function added_signal_should_not_be_null() : Void {
		assertNotNull("Added NativeSignal should not be null", signalSet.added);
	}

	//////
	@:meta(Test())
	public function addedToStage_signal_should_not_be_null() : Void {
		assertNotNull("AddedToStage NativeSignal should not be null", signalSet.addedToStage);
	}

	//////
	@:meta(Test())
	public function enterFrame_signal_should_not_be_null() : Void {
		assertNotNull("EnterFrame NativeSignal should not be null", signalSet.enterFrame);
	}

	//////
	@:meta(Test())
	public function exitFrame_signal_should_not_be_null() : Void {
		assertNotNull("ExitFrame NativeSignal should not be null", signalSet.exitFrame);
	}

	//////
	@:meta(Test())
	public function frameConstructed_signal_should_not_be_null() : Void {
		assertNotNull("FrameConstructed NativeSignal should not be null", signalSet.frameConstructed);
	}

	//////
	@:meta(Test())
	public function removed_signal_should_not_be_null() : Void {
		assertNotNull("Removed NativeSignal should not be null", signalSet.removed);
	}

	//////
	@:meta(Test())
	public function removedFromStage_signal_should_not_be_null() : Void {
		assertNotNull("RemovedFromStage NativeSignal should not be null", signalSet.removedFromStage);
	}

	//////
	@:meta(Test())
	public function render_signal_should_not_be_null() : Void {
		assertNotNull("Render NativeSignal should not be null", signalSet.render);
	}

	//////
	@:meta(Test())
	public function add_added_then_EventDispatcher_dispatch_should_call_signal_listener() : Void {
		signalSet.added.add(async.add(handleEvent));
		sprite.dispatchEvent(new Event(Event.ADDED));
	}

	//////
	@:meta(Test())
	public function add_addedToStage_then_EventDispatcher_dispatch_should_call_signal_listener() : Void {
		signalSet.addedToStage.add(async.add(handleEvent));
		sprite.dispatchEvent(new Event(Event.ADDED_TO_STAGE));
	}

	//////
	@:meta(Test())
	public function add_enterFrame_then_EventDispatcher_dispatch_should_call_signal_listener() : Void {
		signalSet.enterFrame.add(async.add(handleEvent));
		sprite.dispatchEvent(new Event(Event.ENTER_FRAME));
	}

	//////
	@:meta(Test())
	public function add_exitFrame_then_EventDispatcher_dispatch_should_call_signal_listener() : Void {
		signalSet.exitFrame.add(async.add(handleEvent));
		sprite.dispatchEvent(new Event("exitFrame"));
	}

	//////
	@:meta(Test())
	public function add_frameConstructed_then_EventDispatcher_dispatch_should_call_signal_listener() : Void {
		signalSet.frameConstructed.add(async.add(handleEvent));
		sprite.dispatchEvent(new Event("frameConstructed"));
	}

	//////
	@:meta(Test())
	public function add_removed_then_EventDispatcher_dispatch_should_call_signal_listener() : Void {
		signalSet.removed.add(async.add(handleEvent));
		sprite.dispatchEvent(new Event(Event.REMOVED));
	}

	//////
	@:meta(Test())
	public function add_removedFromStage_then_EventDispatcher_dispatch_should_call_signal_listener() : Void {
		signalSet.removedFromStage.add(async.add(handleEvent));
		sprite.dispatchEvent(new Event(Event.REMOVED_FROM_STAGE));
	}

	//////
	@:meta(Test())
	public function add_render_then_EventDispatcher_dispatch_should_call_signal_listener() : Void {
		signalSet.render.add(async.add(handleEvent));
		sprite.dispatchEvent(new Event(Event.RENDER));
	}

	//////
	@:meta(Test())
	public function add_added_then_pause_and_dispatch_should_not_call_signal_listener() : Void {
		var slot : ISlot = signalSet.added.add(failIfCalled);
		slot.enabled = false;
		sprite.dispatchEvent(new Event(Event.ADDED));
	}

	//////
	@:meta(Test())
	public function add_addedToStage_then_pause_and_dispatch_should_not_call_signal_listener() : Void {
		var slot : ISlot = signalSet.addedToStage.add(failIfCalled);
		slot.enabled = false;
		sprite.dispatchEvent(new Event(Event.ADDED_TO_STAGE));
	}

	//////
	@:meta(Test())
	public function add_enterFrame_then_pause_and_dispatch_should_not_call_signal_listener() : Void {
		var slot : ISlot = signalSet.enterFrame.add(failIfCalled);
		slot.enabled = false;
		sprite.dispatchEvent(new Event(Event.ENTER_FRAME));
	}

	//////
	@:meta(Test())
	public function add_exitFrame_then_pause_and_dispatch_should_not_call_signal_listener() : Void {
		var slot : ISlot = signalSet.exitFrame.add(failIfCalled);
		slot.enabled = false;
		sprite.dispatchEvent(new Event("exitFrame"));
	}

	//////
	@:meta(Test())
	public function add_frameConstructed_then_pause_and_dispatch_should_not_call_signal_listener() : Void {
		var slot : ISlot = signalSet.frameConstructed.add(failIfCalled);
		slot.enabled = false;
		sprite.dispatchEvent(new Event("frameConstructed"));
	}

	//////
	@:meta(Test())
	public function add_removed_then_pause_and_dispatch_should_not_call_signal_listener() : Void {
		var slot : ISlot = signalSet.removed.add(failIfCalled);
		slot.enabled = false;
		sprite.dispatchEvent(new Event(Event.REMOVED));
	}

	//////
	@:meta(Test())
	public function add_removedFromStage_then_pause_and_dispatch_should_not_call_signal_listener() : Void {
		var slot : ISlot = signalSet.removedFromStage.add(failIfCalled);
		slot.enabled = false;
		sprite.dispatchEvent(new Event(Event.REMOVED_FROM_STAGE));
	}

	//////
	@:meta(Test())
	public function add_render_then_pause_and_dispatch_should_not_call_signal_listener() : Void {
		var slot : ISlot = signalSet.render.add(failIfCalled);
		slot.enabled = false;
		sprite.dispatchEvent(new Event(Event.RENDER));
	}

	//////
	@:meta(Test())
	public function add_added_then_numListeners_should_be_one() : Void {
		signalSet.added.add(handleEvent);
		assertTrue("Number of listeners should be 1", signalSet.numListeners == 1);
	}

	//////
	@:meta(Test())
	public function add_addedToStage_then_numListeners_should_be_one() : Void {
		signalSet.addedToStage.add(handleEvent);
		assertTrue("Number of listeners should be 1", signalSet.numListeners == 1);
	}

	//////
	@:meta(Test())
	public function add_enterFrame_then_numListeners_should_be_one() : Void {
		signalSet.enterFrame.add(handleEvent);
		assertTrue("Number of listeners should be 1", signalSet.numListeners == 1);
	}

	//////
	@:meta(Test())
	public function add_exitFrame_then_numListeners_should_be_one() : Void {
		signalSet.exitFrame.add(handleEvent);
		assertTrue("Number of listeners should be 1", signalSet.numListeners == 1);
	}

	//////
	@:meta(Test())
	public function add_frameConstructed_then_numListeners_should_be_one() : Void {
		signalSet.frameConstructed.add(handleEvent);
		assertTrue("Number of listeners should be 1", signalSet.numListeners == 1);
	}

	//////
	@:meta(Test())
	public function add_removed_then_numListeners_should_be_one() : Void {
		signalSet.removed.add(handleEvent);
		assertTrue("Number of listeners should be 1", signalSet.numListeners == 1);
	}

	//////
	@:meta(Test())
	public function add_removedFromStage_then_numListeners_should_be_one() : Void {
		signalSet.removedFromStage.add(handleEvent);
		assertTrue("Number of listeners should be 1", signalSet.numListeners == 1);
	}

	//////
	@:meta(Test())
	public function add_render_then_numListeners_should_be_one() : Void {
		signalSet.render.add(handleEvent);
		assertTrue("Number of listeners should be 1", signalSet.numListeners == 1);
	}

	@:meta(Test())
	public function add_all_signals_then_numListeners_should_be_ten() : Void {
		signalSet.activate.add(handleEvent);
		signalSet.deactivate.add(handleEvent);
		signalSet.added.add(handleEvent);
		signalSet.addedToStage.add(handleEvent);
		signalSet.enterFrame.add(handleEvent);
		signalSet.exitFrame.add(handleEvent);
		signalSet.frameConstructed.add(handleEvent);
		signalSet.removed.add(handleEvent);
		signalSet.removedFromStage.add(handleEvent);
		signalSet.render.add(handleEvent);
		assertTrue("Number of listeners should be 10", signalSet.numListeners == 10);
	}

	@:meta(Test())
	public function add_all_signals_then_remove_from_two_and_numListeners_should_be_eight() : Void {
		signalSet.activate.add(handleEvent);
		signalSet.deactivate.add(handleEvent);
		signalSet.added.add(handleEvent);
		signalSet.addedToStage.add(handleEvent);
		signalSet.enterFrame.add(handleEvent);
		signalSet.exitFrame.add(handleEvent);
		signalSet.frameConstructed.add(handleEvent);
		signalSet.removed.add(handleEvent);
		signalSet.removedFromStage.add(handleEvent);
		signalSet.render.add(handleEvent);
		signalSet.addedToStage.removeAll();
		signalSet.exitFrame.removeAll();
		assertTrue("Number of listeners should be 8", signalSet.numListeners == 8);
	}

	@:meta(Test())
	public function add_all_signals_then_removeAll_and_numListeners_should_be_zero() : Void {
		signalSet.activate.add(handleEvent);
		signalSet.deactivate.add(handleEvent);
		signalSet.added.add(handleEvent);
		signalSet.addedToStage.add(handleEvent);
		signalSet.enterFrame.add(handleEvent);
		signalSet.exitFrame.add(handleEvent);
		signalSet.frameConstructed.add(handleEvent);
		signalSet.removed.add(handleEvent);
		signalSet.removedFromStage.add(handleEvent);
		signalSet.render.add(handleEvent);
		signalSet.removeAll();
		assertTrue("Number of listeners should be 0", signalSet.numListeners == 0);
	}

}

